using FytSoa.Application.Crm.Param;
using FytSoa.Application.Erp.Param;
using FytSoa.Common.Enum;
using FytSoa.Common.Extensions;
using FytSoa.Domain.Erp;
using FytSoa.Sugar;
using FytSoa.Common.Result;
using FytSoa.Common.Utils;
using FytSoa.Domain;
using Mapster;
using Masuit.Tools.Reflection;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace FytSoa.Application.Erp;

/// <summary>
/// 生产订单服务接口
/// </summary>
[ApiExplorerSettings(GroupName = "v9")]
public class ErpProduceOrderService : IApplicationService 
{
    private readonly SugarRepository<ErpProduceOrder> _thisRepository;
    private readonly SugarRepository<ErpProduceDetail> _detailRepository;
    private readonly SugarRepository<ErpProduceOrderCraft> _orderCraftRepository;
    private readonly SugarRepository<ErpProduceReject> _rejectRepository;
    private readonly ErpInstockService _instockService;
    private readonly ErpOperateLogService _operateLogService;
    private readonly ErpFlowUseService _flowUseService;
    public ErpProduceOrderService(SugarRepository<ErpProduceOrder> thisRepository
    ,SugarRepository<ErpProduceDetail> detailRepository
    ,SugarRepository<ErpProduceOrderCraft> orderCraftRepository
    ,SugarRepository<ErpProduceReject> rejectRepository
    ,ErpFlowUseService flowUseService
    ,ErpInstockService instockService
    ,ErpOperateLogService operateLogService)
    {
        _thisRepository = thisRepository;
        _detailRepository = detailRepository;
        _orderCraftRepository = orderCraftRepository;
        _rejectRepository = rejectRepository;
        _instockService = instockService;
        _operateLogService = operateLogService;
        _flowUseService = flowUseService;
    }
    
    /// <summary>
    /// 查询所有——分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ErpProduceOrderDto>> GetPagesAsync(ErpProduceOrderSearchParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .WhereIF(param.Audit!=0,m=>m.Status==param.Audit)
            .WhereIF(param.Phase!=0,m=>m.Phase==param.Phase)
            .WhereIF(param.Design!=0,m=>SqlFunc.JsonListObjectAny(m.DesignProcess.Process, "Status", param.Design))
            .WhereIF(!string.IsNullOrEmpty(param.Key),m=>m.Number.Contains(param.Key))
            .Includes(m=>m.Employee)
            .Includes(m=>m.Project)
            .OrderByDescending(m=>m.Id)
            .ToPageAsync(param.Page, param.Limit);
        return query.Adapt<PageResult<ErpProduceOrderDto>>();
    }

    /// <summary>
    /// 根据主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<ErpProduceOrderDto> GetAsync(long id)
    {
        var model = await _thisRepository.AsQueryable()
            .Includes(m=>m.Employee)
            .Includes(m=>m.Project)
            .SingleAsync(m=>m.Id==id);
        var result=model.Adapt<ErpProduceOrderDto>();
        result.Flow = await _flowUseService.GetFlowAsync(model.Id);
        return result;
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task AddAsync(ErpProduceOrderAddParam param)
    {
        var toDay = await _thisRepository.CountAsync(m=>m.CreateTime.ToString("yyyy-MM")==DateTime.Now.ToString("yyyy-MM"));
        param.Order.Number = "OD".ResNumber(toDay,"yyyyMM");
        var orderId=await _thisRepository.InsertReturnSnowflakeIdAsync(param.Order.Adapt<ErpProduceOrder>());
        var detailList=param.Detail.Adapt<List<ErpProduceDetail>>();
        foreach (var item in detailList)
        {
            item.OrderId = orderId;
        }
        await _detailRepository.InsertRangeAsync(detailList);

        var craftList=param.Craft.Adapt<List<ErpProduceOrderCraft>>();
        var addCraftList = new List<ErpProduceOrderCraft>();
        var productIdKey = craftList.GroupBy(m => m.ProductId).Select(m=>m.Key).ToList();
        foreach (var row in productIdKey)
        {
            var craftNumber = 0;
            foreach (var item in craftList.Where(m=>m.ProductId==row))
            {
                craftNumber += 1;
                item.Number = craftNumber;
                item.OrderId = orderId;
                addCraftList.Add(item);
            }
        }
        await _orderCraftRepository.InsertRangeAsync(addCraftList);
        
        if (param.Order.FlowId!=0)
        {
            await _flowUseService.AddAsync(new ErpFlowUseDto()
            {
                FlowId=param.Order.FlowId,
                UseId=orderId,
                Type = FlowTypeEnum.ProductionOrder,
            });
        }
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = orderId,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = "创建了生产订单信息【"+param.Order.Number+"】"
        });
    }


    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyAsync(ErpProduceOrderAddParam param)
    {
        //先删除
        await _detailRepository.DeleteAsync(m=>m.OrderId==param.Order.Id);
        await _orderCraftRepository.DeleteAsync(m=>m.OrderId==param.Order.Id);
        //添加
        var detailList=param.Detail.Adapt<List<ErpProduceDetail>>();
        foreach (var item in detailList)
        {
            item.OrderId = param.Order.Id;
        }
        await _thisRepository.UpdateAsync(param.Order.Adapt<ErpProduceOrder>());
        await _detailRepository.InsertRangeAsync(detailList);
        
        //添加工艺流程
        var craftList=param.Craft.Adapt<List<ErpProduceOrderCraft>>();
        var number = 0;
        foreach (var item in craftList)
        {
            number += 1;
            item.Number = number;
            item.OrderId = param.Order.Id;
        }

        await _orderCraftRepository.InsertRangeAsync(craftList);
        
        if (param.Order.Status == ErpAuditEnum.NotReviewed)
        {
            await _flowUseService.ModifyAsync(new ErpFlowUseDto()
            {
                FlowId = param.Order.FlowId,
                UseId = param.Order.Id,
                Type = FlowTypeEnum.ProductionOrder,
            });
        }
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = param.Order.Id,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = "编辑了生产订单信息【"+param.Order.Number+"】"
        });
    }
    
    /// <summary>
    /// 修改状态
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyStatusAsync(ErpStatusParam param)
    {
        await _thisRepository.UpdateAsync(m=>new ErpProduceOrder()
        {
            Status = param.Status
        },m=>param.Ids.Contains(m.Id));
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateIds = param.Ids,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = "对生产订单做了审核通过操作"
        });
        
        if (param.Status==ErpAuditEnum.InReview)
        {
            foreach (var item in param.Ids)
            {
                await _flowUseService.StartAuditAsync(item, FlowTypeEnum.ProductionOrder);
            }
        }
    }
    
    /// <summary>
    /// 更改生产订单阶段
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyPhaseAsync(ErpProducePhaseParam param)
    {
        //判断推送至品控，是否生产任务以全部完成
        if (param.Phase == ErpProducePhaseEnum.QualityControl)
        {
            var isAny = await _orderCraftRepository.IsAnyAsync(m => m.OrderId == param.Ids[0] && m.Status!=3);
            if (isAny)
            {
                throw new BusinessException("需要生产任务全部完成后，才允许推至品控！");
            }
        }
        
        if (param.Phase == ErpProducePhaseEnum.Close)
            await _thisRepository.UpdateAsync(m => new ErpProduceOrder()
            {
                Phase = param.Phase,
                CloseRemark = param.Remark
            }, m => param.Ids.Contains(m.Id));
        else
            await _thisRepository.UpdateAsync(m => new ErpProduceOrder()
            {
                Phase = param.Phase
            }, m => param.Ids.Contains(m.Id));

        var closeTip = string.Empty;
        if (param.Phase==ErpProducePhaseEnum.Close)
        {
            closeTip = "，关闭原因："+param.Remark;
        }
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateIds = param.Ids,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = "变更了生产订单，当前状态为："+param.Phase.GetDescription()+closeTip
        });

        if (param.Phase!=ErpProducePhaseEnum.Completed)
        {
            return;
        }
        #region 处理入库

        var inStockEntity = new ErpInstockDto()
        {
            Type = ErpInStockTypeEnum.Production,
            RelationId=param.Ids[0],
            InStockTime=DateTime.Now
        };
        //根据订单编号查询生产物料详细
        var productDetailList = await _detailRepository.GetListAsync(m => m.OrderId == param.Ids[0]);
        var productList = productDetailList.Select(item => 
            new ErpInstockProductDto() { ProductId = item.ProductId, Count = item.Count })
            .ToList();
        await _instockService.AddAsync(new ErpInStockAddParam()
        {
            inStock=inStockEntity,
            Product = productList
        });

        #endregion
    }
    
    /// <summary>
    /// 更改生产订单品控状态
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyControlAsync(ErpProduceControlParam param)
    {
        var model = await _thisRepository.GetByIdAsync(param.Id);
        if (param.Status==ErpProduceStatusEnum.Completed)
        {
            //计算工时
            var timeDifference = DateTime.Now - model.ControlProcess.Last().Time; 
            model.ControlHour = Math.Round(timeDifference.TotalHours,1); 
        }
        model.ControlProcess.Add(new ErpProduceOrder.DesignProcessModel.ProcessModel()
        {
            Status = (int)param.Status,
            EmployeeName = AppUtils.LoginUser,
            EmployeeId = AppUtils.EmployeeId
        });
        model.ControlStatus = (int)param.Status;
        // 驳回操作
        if (param.Status==ErpProduceStatusEnum.Reject)
        {
            // 发配至生产阶段
            model.Phase = ErpProducePhaseEnum.Production;
            // 增加一条工艺流程
            var craftModel =
                await _orderCraftRepository.GetFirstAsync(m => m.Id == param.Craft);
            craftModel.Status = (int) ErpProduceStatusEnum.Pending;
            var craftCount=await _orderCraftRepository.CountAsync(m => m.OrderId == param.Id);
            craftModel.Id = 0;
            craftModel.Number = craftCount + 1;
            craftModel.WorkHour = 0;
            craftModel.Remark = param.Cause;
            craftModel.IsReject = true;
            craftModel.StatusProcess = new ();
            var ordreCraftId= await _orderCraftRepository.InsertReturnSnowflakeIdAsync(craftModel);
            // 增加关系驳回数据
            await _rejectRepository.InsertAsync(new ErpProduceReject()
            {
                Number = StringUtils.OrderNumber(),
                OrderId = param.Id,
                CraftId = craftModel.CraftId,
                RelationId = ordreCraftId,
                Cause = param.Cause
            });
        }
        await _thisRepository.UpdateAsync(model);
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = param.Id,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = "生产订单，变更了品控流程状态为："+param.Status.GetDescription()
        });
    }
    
    /// <summary>
    /// 更新附件
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task<List<FileBase>> ModifyFileAsync(CrmContractFilesParam model)
    {
        var contract = await _thisRepository.GetFirstAsync(m => m.Id == model.Id);
        if (contract.Files.Count==0)
        {
            contract.Files = new List<FileBase>();
        }
        contract.Files.Add(model.File);
        await _thisRepository.UpdateAsync(contract);
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = model.Id,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = "更新了生产订单-设计的附件信息"
        });
        return contract.Files;
    }
    
    /// <summary>
    /// 更改设计状态接受/已开工/已完成
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task ModifyDesignAsync(ErpProduceOrderDesignParam param)
    {
        var list = await _thisRepository.GetListAsync(m => param.Ids.Contains(m.Id));
        foreach (var item in list)
        {
            if (param.Status==(int)ErpProduceStatusEnum.Completed)
            {
                //计算工时
                var timeDifference = DateTime.Now - item.DesignProcess.Process[1].Time;  // 计算时间差异
                item.DesignProcess.Hour = Math.Round(timeDifference.TotalHours,1); 
            }
            item.DesignProcess.Process.Add(new ErpProduceOrder.DesignProcessModel.ProcessModel()
            {
                Status = param.Status
            });
        }

        await _thisRepository.UpdateRangeAsync(list);
        var message = param.Status switch
        {
            1 => "【接受了】生产订单的设计工作",
            2 => "【开始了】生产订单的设计工作",
            3 => "【完成了】生产订单的设计工作",
            _ => string.Empty
        };
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateIds = param.Ids,
            Type = (int)ErpOperateEnum.ProduceOrder,
            Remark = message
        });
    }

    /// <summary>
    /// 删除,支持批量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [HttpDelete,UnitOfWork]
    public async Task DeleteAsync([FromBody] List<long> ids)
    {
        await _thisRepository.DeleteAsync(m=>ids.Contains(m.Id));
        await _detailRepository.DeleteAsync(m=>ids.Contains(m.OrderId));
        await _orderCraftRepository.DeleteAsync(m => ids.Contains(m.OrderId));
        await _flowUseService.DeleteAsync(ids);
    }
}
